package fr.nghs.android.thport.gestures;

import fr.nghs.android.common.MathUtils;
import fr.nghs.android.common.ScaleGestureDetector;
import fr.nghs.android.thport.THSurface;

/**
 * Surface discrete zoom (2 states) & offset
 * Using 2 fingers pinch-to-zoom
 * @author ng
 *
 */
public class SurfaceMoveAndDiscreteScale
    implements ScaleGestureDetector.OnScaleGestureListener
{
    private static final float ZOOM_MINMIUM = 1.00f;
    private static final float ZOOM_MAXIMUM = 2.00f;
    private static final float ZOOM_MARGIN = 0.25f; // margin around max & min
    
    private static final float ZOOM_DEV_FACTOR = 1.3f; // factor from device zoom
    
    private float prevX, prevY;
    private float rawZoom = 1f, zoom = 1f;
    private int xOffset = 0, yOffset = 0, w, h;

    private THSurface surface;
    
    public SurfaceMoveAndDiscreteScale(THSurface s)
    {
        surface = s;
    }
    
    @Override
    public boolean onScaleBegin(ScaleGestureDetector s)
    {
        prevX = Float.NaN;
        w = surface.getWidth();
        h = surface.getHeight();
        return true;
    }
    
    @Override
    public boolean onScale(ScaleGestureDetector s)
    {
        final float x = s.getFocusX();
        final float y = s.getFocusY();
        final float z = s.getScaleFactor();
        
        //rawZoom *= z;
        rawZoom = MathUtils.ensureRange(rawZoom * z, ZOOM_MINMIUM, ZOOM_DEV_FACTOR*ZOOM_MAXIMUM);
        
        if(rawZoom <= ZOOM_MINMIUM + ZOOM_MARGIN)
            zoom = ZOOM_MINMIUM;
        else if(rawZoom >= ZOOM_DEV_FACTOR*ZOOM_MAXIMUM - ZOOM_MARGIN)
            zoom = ZOOM_MAXIMUM;

        boolean isFirst = Float.isNaN(prevX);
        
        if(isFirst)
        {
        }
        else
        {
            xOffset += x - prevX;
            yOffset += y - prevY;
            
            //Log.d("NGHSTH", "w="+w+" zoom="+zoom+" w*zoom="+(w*zoom) + " w*(1-zoom)=" +(int)(w * (1 - zoom)) + " xoffset="+xOffset+ " yoffset="+yOffset);
            
            yOffset = MathUtils.ensureRange(yOffset, (int)(h * (1 - zoom)), 0);
            xOffset = MathUtils.ensureRange(xOffset, (int)(w * (1 - zoom)), 0);

            surface.setOffsetAndScale(xOffset, yOffset, zoom);
        }
        
        prevX = x;
        prevY = y;
        return true;

    }

    @Override
    public void onScaleEnd(ScaleGestureDetector s)
    {
        if(zoom == ZOOM_MINMIUM)
            rawZoom = ZOOM_MINMIUM;
        else
            rawZoom = ZOOM_DEV_FACTOR*ZOOM_MAXIMUM;
    }

}
